package com.zg.datapush.util;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 数据推送工具类
 * @author zg
 */
@Slf4j
public class DataPushUtil {

    // SQL注入防护的正则表达式
    private static final Pattern SQL_INJECTION_PATTERN = Pattern.compile(
        "(?i)(\\b(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE|ALTER|EXEC|UNION|SCRIPT)\\b)|[';\"\\-\\-]"
    );

    /**
     * 验证表名是否安全（防止SQL注入）
     */
    public static boolean isValidTableName(String tableName) {
        if (StrUtil.isBlank(tableName)) {
            return false;
        }

        // 表名只能包含字母、数字、下划线
        return tableName.matches("^[a-zA-Z_][a-zA-Z0-9_]*$") &&
               !SQL_INJECTION_PATTERN.matcher(tableName).find();
    }

    /**
     * 验证字段名是否安全（防止SQL注入）
     */
    public static boolean isValidFieldName(String fieldName) {
        if (StrUtil.isBlank(fieldName)) {
            return false;
        }

        // 字段名只能包含字母、数字、下划线
        return fieldName.matches("^[a-zA-Z_][a-zA-Z0-9_]*$") &&
               !SQL_INJECTION_PATTERN.matcher(fieldName).find();
    }

    /**
     * 清理SQL字符串，防止注入
     */
    public static String sanitizeSql(String sql) {
        if (StrUtil.isBlank(sql)) {
            return sql;
        }

        // 移除潜在的危险字符
        return sql.replaceAll("[';\"\\-\\-]", "");
    }

    /**
     * 构建安全的WHERE条件
     */
    public static String buildSafeWhereCondition(String fieldName, String operator, Object value) {
        if (!isValidFieldName(fieldName)) {
            throw new IllegalArgumentException("无效的字段名: " + fieldName);
        }

        if (StrUtil.isBlank(operator)) {
            operator = "=";
        }

        // 验证操作符
        if (!isValidOperator(operator)) {
            throw new IllegalArgumentException("无效的操作符: " + operator);
        }

        if (value instanceof String) {
            return String.format("%s %s '%s'", fieldName, operator, sanitizeValue(value.toString()));
        } else {
            return String.format("%s %s %s", fieldName, operator, value);
        }
    }

    /**
     * 验证操作符是否有效
     */
    private static boolean isValidOperator(String operator) {
        String[] validOperators = {"=", "!=", "<>", ">", "<", ">=", "<=", "LIKE", "IN", "NOT IN"};
        for (String validOp : validOperators) {
            if (validOp.equalsIgnoreCase(operator)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 清理值，防止注入
     */
    private static String sanitizeValue(String value) {
        if (value == null) {
            return null;
        }

        // 转义单引号
        return value.replace("'", "''");
    }

    /**
     * 解析连接字符串中的参数
     */
    public static Map<String, String> parseConnectionParams(String connectionUrl) {
        Map<String, String> params = new HashMap<>();

        if (StrUtil.isBlank(connectionUrl)) {
            return params;
        }

        try {
            // 提取URL中的参数部分
            int questionMarkIndex = connectionUrl.indexOf('?');
            if (questionMarkIndex > 0 && questionMarkIndex < connectionUrl.length() - 1) {
                String paramString = connectionUrl.substring(questionMarkIndex + 1);
                String[] paramPairs = paramString.split("&");

                for (String pair : paramPairs) {
                    String[] keyValue = pair.split("=", 2);
                    if (keyValue.length == 2) {
                        params.put(keyValue[0], keyValue[1]);
                    }
                }
            }
        } catch (Exception e) {
            log.warn("解析连接参数失败: {}", connectionUrl, e);
        }

        return params;
    }

    /**
     * 构建数据库连接URL
     */
    public static String buildConnectionUrl(String dbType, String host, int port, String database, Map<String, String> params) {
        StringBuilder url = new StringBuilder();

        switch (dbType.toLowerCase()) {
            case "mysql":
                url.append("jdbc:mysql://").append(host).append(":").append(port).append("/").append(database);
                break;
            case "postgresql":
                url.append("jdbc:postgresql://").append(host).append(":").append(port).append("/").append(database);
                break;
            case "oracle":
                url.append("jdbc:oracle:thin:@").append(host).append(":").append(port).append(":").append(database);
                break;
            case "sqlserver":
                url.append("jdbc:sqlserver://").append(host).append(":").append(port).append(";databaseName=").append(database);
                break;
            default:
                throw new IllegalArgumentException("不支持的数据库类型: " + dbType);
        }

        // 添加参数
        if (params != null && !params.isEmpty()) {
            boolean first = true;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (first) {
                    url.append("?");
                    first = false;
                } else {
                    url.append("&");
                }
                url.append(entry.getKey()).append("=").append(entry.getValue());
            }
        }

        return url.toString();
    }

    /**
     * 获取数据库类型对应的驱动类名
     */
    public static String getDriverClassName(String dbType) {
        switch (dbType.toLowerCase()) {
            case "mysql":
                return "com.mysql.cj.jdbc.Driver";
            case "postgresql":
                return "org.postgresql.Driver";
            case "oracle":
                return "oracle.jdbc.OracleDriver";
            case "sqlserver":
                return "com.microsoft.sqlserver.jdbc.SQLServerDriver";
            default:
                throw new IllegalArgumentException("不支持的数据库类型: " + dbType);
        }
    }

    /**
     * 验证数据库连接参数
     */
    public static boolean validateConnectionParams(String host, Integer port, String database, String username) {
        if (StrUtil.isBlank(host) || StrUtil.isBlank(database) || StrUtil.isBlank(username)) {
            return false;
        }

        if (port == null || port <= 0 || port > 65535) {
            return false;
        }

        // 验证主机名格式
        if (!host.matches("^[a-zA-Z0-9.-]+$")) {
            return false;
        }

        // 验证数据库名格式
        if (!database.matches("^[a-zA-Z0-9_-]+$")) {
            return false;
        }

        return true;
    }

    /**
     * 格式化数据大小
     */
    public static String formatDataSize(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.2f KB", bytes / 1024.0);
        } else if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", bytes / (1024.0 * 1024));
        } else {
            return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
        }
    }

    /**
     * 格式化执行时间
     */
    public static String formatDuration(long milliseconds) {
        if (milliseconds < 1000) {
            return milliseconds + " ms";
        } else if (milliseconds < 60000) {
            return String.format("%.2f s", milliseconds / 1000.0);
        } else if (milliseconds < 3600000) {
            return String.format("%.2f min", milliseconds / 60000.0);
        } else {
            return String.format("%.2f h", milliseconds / 3600000.0);
        }
    }
}
